// @Author yy 2024/8/23
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

func main() {
	m3u8URL := "https://zhishubucket-beijing.oss-cn-beijing.aliyuncs.com/leaderVideoFile/1816648283754381314/c3aad93ab241eb9e22c9dc993eb736d2_1816648283754381314__uid_s_505__uid_e_audio.m3u8"
	tempDir := "D:\\123123123123"
	outputFile := "123.mp3"

	// 创建临时目录
	err := os.MkdirAll(tempDir, os.ModePerm)
	if err != nil {
		fmt.Println("无法创建临时目录:", err)
		return
	}
	defer os.RemoveAll(tempDir)

	// 下载M3U8文件
	m3u8Content, err := downloadFile(m3u8URL)
	if err != nil {
		fmt.Println("无法下载M3U8文件:", err)
		return
	}

	// 解析M3U8文件获取片段URL
	segmentURLs, err := parseM3U8(m3u8Content)
	if err != nil {
		fmt.Println("无法解析M3U8文件:", err)
		return
	}

	// 下载所有片段
	err = downloadSegments(segmentURLs, tempDir)
	if err != nil {
		fmt.Println("无法下载片段:", err)
		return
	}

	// 合并片段
	err = mergeSegments(tempDir, outputFile)
	if err != nil {
		fmt.Println("无法合并片段:", err)
		return
	}

	// 转换格式
	err = convertToMP3(outputFile)
	if err != nil {
		fmt.Println("无法转换格式:", err)
		return
	}

	fmt.Println("转换完成！")
}

// 下载文件
func downloadFile(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

// 解析M3U8文件获取片段URL
func parseM3U8(content []byte) ([]string, error) {
	lines := strings.Split(string(content), "\n")
	var urls []string
	for _, line := range lines {
		if strings.HasPrefix(line, "http") {
			urls = append(urls, line)
		}
	}
	return urls, nil
}

// 下载片段
func downloadSegments(urls []string, dir string) error {
	for _, url := range urls {
		resp, err := http.Get(url)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		out, err := os.Create(dir + "/" + getFileNameFromURL(url))
		if err != nil {
			return err
		}
		defer out.Close()

		_, err = io.Copy(out, resp.Body)
		if err != nil {
			return err
		}
	}
	return nil
}

// 合并片段
func mergeSegments(dir string, outputFile string) error {
	files, err := os.ReadDir(dir)
	if err != nil {
		return err
	}

	var args []string
	for _, file := range files {
		args = append(args, dir+"/"+file.Name())
	}
	args = append(args, outputFile)

	cmd := exec.Command("ffmpeg", args...)
	err = cmd.Run()
	if err != nil {
		return err
	}

	return nil
}

// 转换格式
func convertToMP3(inputFile string) error {
	cmd := exec.Command("ffmpeg", "-i", inputFile, "-vn", "-acodec", "libmp3lame", inputFile+".mp3")
	err := cmd.Run()
	if err != nil {
		return err
	}

	return nil
}

// 从URL获取文件名
func getFileNameFromURL(url string) string {
	parts := strings.Split(url, "/")
	return parts[len(parts)-1]
}
